"""
===============================
@author     : yaoruiqi

@Time       : 2023/3/3 16:29

@version    : V

@introduce  :

@change     : 
===============================
"""
import asyncio
from time import strftime, localtime

from asgiref.sync import sync_to_async
from django.core.cache import cache
from loguru import logger

from api.wechat_api import template_message
from app_subscription_account.models import SubscriptionUser
from beachburg_joint_plan.settings import SERVICE_BASE_INFO


def response_json(**kwargs):
    return {
        'code': kwargs.get('code', 0),
        'message': kwargs.get('message', ''),
        'data': kwargs.get('data', '')
    }


def get_access_token(service_name: str):
    """
    获取服务access_token
    @param service_name: 服务名称  可用参数见 SERVICE_BASE_INFO
    @return:
    """
    try:
        assert service_name in SERVICE_BASE_INFO.keys(), '获取access_token参数错误: service_name'
        access_token = cache.get(f'access_token:{service_name}')
        assert access_token, f'未获取到access_token  service: {service_name}'
        return access_token
    except Exception as e:
        logger.exception(f'获取服务access_token失败')
        raise e


def get_developer_open_id():
    try:
        cache_data = cache.get('developer_open_id')
        if cache_data:
            return cache_data.split(';')
        else:
            user_objs = SubscriptionUser.objects.filter(role='developer').values('openid')
            developer_list = [i['openid'] for i in user_objs]
            cache.set('developer_open_id', ';'.join(developer_list))
            return developer_list
    except Exception as e:
        logger.exception(f'查询开发者open_id失败')
        raise e


class SendFunUpdateTemplate:

    @staticmethod
    def get_all_openid():
        """ 获取推送公众号所有订阅用户open_id """
        return (i['openid'] for i in SubscriptionUser.objects.filter(subscribe=1).values('openid'))

    async def manager(self, access_token: str, update_content: str, all_user_openid: list = None):
        """
        异步发送小程序版本更新公告
        @param access_token: 服务access_token
        @param update_content: 公告内容
        @param all_user_openid: 可以选择指定部分用户open_id
        """
        if all_user_openid is None:
            all_user_openid = await sync_to_async(self.get_all_openid)()
        assert all_user_openid, '查询公众号所有订阅用户openid失败'

        fun_update_task_list = []

        for openid in all_user_openid:
            fun_update_task_list.append(
                template_message.async_send_tempalte_massage(
                    access_token=access_token,
                    user_open_id=openid,
                    template_name='功能更新',
                    time=strftime("%Y-%m-%d", localtime()),
                    content=update_content
                )
            )
        for result in await asyncio.gather(*fun_update_task_list):
            if not result:
                for developer_open_id in get_developer_open_id():
                    template_message.send_template_message(
                        access_token=get_access_token(service_name='subscription_tips'),
                        user_open_id=developer_open_id,
                        template_name='服务异常通知',
                        time=strftime("%Y-%m-%d %H:%M:%S", localtime()),
                        service_name='版本更新',
                        feedback='版本更新公告推送失败'
                    )
                return False

    def start(self, update_content_list: list, all_user_openid: list = None):
        """
        给所有关注者发送小程序版本更新公告
        @param update_content_list: 公告内容列表
        @param all_user_openid: 可以选择指定部分用户open_id
        @return:
        """
        access_token = get_access_token(service_name='subscription_tips')
        update_content = '\n'.join([f'{_id + 1}. {i}' for _id, i in enumerate(update_content_list)])
        asyncio.run(self.manager(access_token, update_content, all_user_openid))


if __name__ == '__main__':
    SendFunUpdateTemplate().start(
        [
            '现在比奇堡和每日推送公众号增加简单的信息回复，发送随意内容后系统将会返回目前所有支持的命令哦(tips:除系统更新外，每8小时只告知一次命令哦)'],
        # ['omWX86jfjCgL114ARUJYZw6l64-M']
    )
